package cn.com.dhcc.app.pub.module.resmgr.service;

import java.util.ArrayList;
import java.util.Collection;
import java.util.Date;
import java.util.HashMap;
import java.util.Iterator;
import java.util.LinkedHashMap;
import java.util.List;
import java.util.Map;

import org.apache.log4j.Logger;
import org.springframework.jdbc.core.SingleColumnRowMapper;
import org.springframework.stereotype.Service;
import org.springframework.util.StringUtils;

import cn.com.dhcc.app.core.base.BaseController;
import cn.com.dhcc.app.core.base.BaseService;
import cn.com.dhcc.app.core.base.CmCommon;
import cn.com.dhcc.app.core.base.Dao;
import cn.com.dhcc.app.core.base.cache.CacheGroupName;
import cn.com.dhcc.app.core.base.log.LogType;
import cn.com.dhcc.app.core.component.cache.CacheService;
import cn.com.dhcc.app.core.component.db.SingleTransationCircleWithOutResult;
import cn.com.dhcc.app.core.component.db.orm.WhereCondition;
import cn.com.dhcc.app.core.component.log.Log;
import cn.com.dhcc.app.core.exception.DaoException;
import cn.com.dhcc.app.core.exception.IllegalUserSessionException;
import cn.com.dhcc.app.core.exception.NiceException;
import cn.com.dhcc.app.core.exception.ServiceException;
import cn.com.dhcc.app.core.para.CorePara.CoreInitCtx;
import cn.com.dhcc.app.core.para.ParaGetTool;
import cn.com.dhcc.app.core.tag.CommonStaticCode.OPERATION_TYPE;
import cn.com.dhcc.app.core.tag.CommonStaticCode.YESNO;
import cn.com.dhcc.app.core.util.CollectionUtil;
import cn.com.dhcc.app.core.util.StrUtil;
import cn.com.dhcc.app.core.util.UUIDGenerator;
import cn.com.dhcc.app.pub.core.Table;
import cn.com.dhcc.app.pub.core.Table.SYS_BASE_TABLE;
import cn.com.dhcc.app.pub.module.resmgr.vo.LinkResource;
import cn.com.dhcc.app.pub.module.resmgr.vo.LinkResource.LinkOwnerType;
import cn.com.dhcc.app.pub.module.resmgr.vo.MenuResource;
/**
 * 资源管理service
 * @日期：2013-5-30下午3:54:21
 * @作者：乔兵
 * @版权所有：东华软件
 * @版本：1.0
 */
@Service
public class ResourceService extends BaseService {
	private static Logger logger = Log.getLogger(LogType.SYSINNER);
	public static final String CACHEED_RESOURCE_ID_MENUS_COLLECTION_KEY = "_RES_KEY_ID_MENUS";
	public static final String CACHEED_RESOURCE_ID_LINKS_COLLECTION_KEY = "_RES_KEY_ID_LINKS";
	public static final String CACHEED_RESOURCE_URL_COLLECTION_KEY = "_RES_URL_KEY_";
	
	public static final String CACHEED_PUBLIC_URL_COLLECTION_KEY = "_PUBLIC_RUL";
	public static final String CACHEED_PUBLIC_RESOURCE_COLLECTION_KEY = "_PUBLIC_RESOURCE";

	public static CacheService getCacheService(){
		return CmCommon.getCacheService();
	}
	/**
	 * 添加资源
	 * @param resource 
	 * @param selectedNodeId 选中的资源id
	 * @param operationType 操作类型 
	 * @param type 顶部菜单，左侧菜单，操作
	 * @throws ServiceException
	 * @throws NiceException
	 * @throws IllegalUserSessionException
	 */
	static String RES_ROOT_ID="0";
	public void addResource(final MenuResource resource,String[] linkGroups, final LinkResource linkResource,final String selectedNodeId, String operationType, String type) throws ServiceException, NiceException, IllegalUserSessionException {
		//在当前节点之前添加菜单
		final Dao dao = getDao();
		MenuResource selectedUrlResource = null;
		if(RES_ROOT_ID.equalsIgnoreCase(selectedNodeId)){
			selectedUrlResource = new MenuResource();
			selectedUrlResource.setId(RES_ROOT_ID);	
		}else{
			selectedUrlResource = getMenuResourceById(selectedNodeId);
			if(selectedUrlResource==null)throw new NiceException("id 为"+selectedNodeId+" 的菜单已经不存在！");
		}
		resource.setType(type);
		resource.setModified(new Date());
		resource.setMuid(BaseController.getUid());
		if("addResourceBefore".equalsIgnoreCase(operationType)||"addResourceAfter".equalsIgnoreCase(operationType)){
			resource.setPid(selectedUrlResource.getPid());
			if("addResourceBefore".equalsIgnoreCase(operationType)){
				resource.setOrdNum(selectedUrlResource.getOrdNum());
			}else{
				resource.setOrdNum(selectedUrlResource.getOrdNum()+1);
			}
			final String updateOrdNum_sql = "update "+WSD_TABLE(SYS_BASE_TABLE.SYS_BASE_MENU)+" t set t.ordnum=t.ordnum+1 where t.pid=? and t.ordnum>=?";
			try {
				dao.doInSingleTransationCircle("新增菜单", new SingleTransationCircleWithOutResult() {
					@Override
					public void actionInCircle() throws RuntimeException {
						try {
							dao.update("菜单排序", updateOrdNum_sql, new Object[]{resource.getPid(),resource.getOrdNum()});
							dao.insertModule("新增菜单", resource);
						} catch (DaoException e) {
							throw new RuntimeException(e);
						}
					}
				});
			} catch (DaoException e) {
				throw new ServiceException(e);
			}
		//如果下方没有子节点 用这个操作，如果有了，就用上面的两个操作
		}else if("addChildResource".equalsIgnoreCase(operationType)){
			/*if(UrlResource.ResourceType.LEFT.getType().equals(selectedUrlResource.getType())){//则只能是LEFT
				resource.setType(selectedUrlResource.getType());
			}*/
			resource.setPid(selectedUrlResource.getId());
			Integer maxOrderNum = getMenuMaxOrderNum(selectedUrlResource.getId());
			resource.setOrdNum(maxOrderNum==0?1:maxOrderNum+1);
			try {
				dao.insertModule("新增菜单", resource);
			} catch (DaoException e) {
				throw new ServiceException(e);
			}
		}else if("addActionGroup".equalsIgnoreCase(operationType)){
			resource.setPid(selectedUrlResource.getId());
			Integer maxOrderNum = getMenuMaxOrderNum(selectedUrlResource.getId());
			resource.setOrdNum(maxOrderNum==0?1:maxOrderNum+1);
			try {
				dao.insertModule("新增链接分组", resource);
			} catch (DaoException e) {
				throw new ServiceException(e);
			}
		}else if("addAction".equalsIgnoreCase(operationType)){
			if(!StrUtil.isAllNotBlank(linkGroups)){
				throw new NiceException("请选择分组!");
			}
			final String newLinkId = UUIDGenerator.getUUID(); 
			linkResource.setId(newLinkId);
			final String insertMenuAction = "insert into "+WSD_TABLE(SYS_BASE_TABLE.SYS_BASE_REL_MENU_LINK)+"(menu_id,link_id) values(?,?)"; 
			final List<Object[]> args = new ArrayList<Object[]>();
			if(StrUtil.isAllNotBlank(linkGroups)){
				for (int i = 0; i < linkGroups.length; i++) {
					Object[] arg = new Object[]{linkGroups[i],newLinkId};
					args.add(arg);
				}
			}
			try {
				dao.doInSingleTransationCircle("新增链接", new SingleTransationCircleWithOutResult() {
					@Override
					public void actionInCircle() throws RuntimeException {
						try {
							dao.insertModule("新增操作", linkResource);
							dao.batchInsert("新增分组链接关系", insertMenuAction, args);
							
						} catch (DaoException e) {
							throw new RuntimeException(e);
						}
					}
				});
			} catch (DaoException e) {
				throw new ServiceException(e);
			}
		}
		loadResourceToCache();
	}
	/**
	 * 获取同级菜单排序的最大值
	 * @param pid
	 * @return
	 * @throws ServiceException
	 */
	public Integer getMenuMaxOrderNum(String pid) throws ServiceException {
		String maxOrderSql = null;
		if(getDao().isMysql()){
			maxOrderSql = "SELECT IFNULL(max(ORDNUM),0) FROM "+WSD_TABLE(SYS_BASE_TABLE.SYS_BASE_MENU)+" t where t.pid=?";
		}else{
			maxOrderSql = "SELECT nvl(max(ORDNUM),0) FROM "+WSD_TABLE(SYS_BASE_TABLE.SYS_BASE_MENU)+" t where t.pid=?";
		}
		try {
			return CmCommon.getDao().queryForInt("获取子菜单排序的最大值", maxOrderSql,new Object[]{pid});
		} catch (DaoException e) {
			throw new ServiceException(e);
		}
	}
	/**
	 * 根据id获取链接信息
	 * @param id
	 * @return
	 * @throws ServiceException
	 */
	public LinkResource getLinkResourceById(String id) throws ServiceException {
		LinkResource selectedUrlResource = null;
		try {
			selectedUrlResource = getDao().getModuleById("获取链接信息", LinkResource.class,new Object[]{id});
		} catch (DaoException e) {
			throw new ServiceException(e);
		}
		return selectedUrlResource;
	}
	/**
	 * 根据菜单id获取链接列表信息
	 * @param id
	 * @return
	 * @throws ServiceException
	 */
	public static List<LinkResource> getLinkResourcesByMenuId(String menuId) throws ServiceException {
		String sql = "select l.* from "+WSD_TABLE(SYS_BASE_TABLE.SYS_BASE_LINK)+" l,"+WSD_TABLE(SYS_BASE_TABLE.SYS_BASE_REL_MENU_LINK)+" ml where l.id=ml.link_id and ml.menu_id=?";
		List<LinkResource> selectedUrlResource = null;
		try {
			selectedUrlResource = CmCommon.getDao().listModule("获取链接信息",sql, LinkResource.class,new Object[]{menuId});
		} catch (DaoException e) {
			throw new ServiceException(e);
		}
		return selectedUrlResource;
	}
	
	/**
	 * 根据id获取资源属性。如果当前资源不是操作并且是叶子菜单查出所关联的操作
	 * @param id
	 * @return
	 * @throws ServiceException
	 */
	public MenuResource getMenuResourceById(String id) throws ServiceException {
		return getMenuResourceFromCache(id);
	}
	/**
	 * 修改菜单资源
	 * @param resource
	 * @throws ServiceException
	 * @throws IllegalUserSessionException
	 */
	public void updateMenuResource(MenuResource resource) throws ServiceException, IllegalUserSessionException {
		try {
			WhereCondition updateParameter = new WhereCondition();
			updateParameter.where().eq("ID", resource.getId());
			resource.setModified(new Date());
			resource.setMuid(BaseController.getUid());
			getDao().updateModule("修改菜单", resource, updateParameter);
			
			loadResourceToCache();
		} catch (DaoException e) {
			throw new ServiceException(e);
		}
		
	}
	/**
	 * 修改链接资源
	 * @param resource
	 * @param linkGroups 
	 * @throws ServiceException
	 * @throws IllegalUserSessionException
	 */
	public void updateLinkResource(final LinkResource resource, String[] linkGroups) throws ServiceException, IllegalUserSessionException {
		try {
			//修改连接信息，删除关系，重新添加关系
			final String deleteMenuLinkRel = "delete from "+WSD_TABLE(SYS_BASE_TABLE.SYS_BASE_REL_MENU_LINK)+"  where link_id=?";
			final String insertMenuAction = "insert into "+WSD_TABLE(SYS_BASE_TABLE.SYS_BASE_REL_MENU_LINK)+"(menu_id,link_id) values(?,?)"; 
			final List<Object[]> args = new ArrayList<Object[]>();
			
			if(StrUtil.isAllNotBlank(linkGroups)){
				for (int i = 0; i < linkGroups.length; i++) {
					Object[] arg = new Object[]{linkGroups[i],resource.getId()};
					args.add(arg);
				}
			}
			WhereCondition updateParameter = new WhereCondition();
			updateParameter.where().eq("ID", resource.getId());
			resource.setModified(new Date());
			resource.setMuid(BaseController.getUid());
			getDao().doInSingleTransationCircle("修改链接菜单", new SingleTransationCircleWithOutResult() {
				
				@Override
				public void actionInCircle() throws RuntimeException {
					try {
						getDao().updateModuleById("修改链接菜单", resource, null);
						getDao().delete("删除菜单链接关系", deleteMenuLinkRel, new Object[]{resource.getId()});
						getDao().batchInsert("新增菜单链接关系", insertMenuAction, args);
					} catch (DaoException e) {
						throw new RuntimeException(e);
					}
				}
			});
			loadResourceToCache();
		} catch (DaoException e) {
			throw new ServiceException(e);
		}
	}
	/**
	 * 删除资源，同事删除下方的子菜单和操作，同时对同级菜单从当前菜单往后进行重新排序
	 * @param id
	 * @throws ServiceException
	 */
	public void deleteLinkResource(final String id) throws ServiceException {
		 final String update_actionid_sql = "UPDATE "+WSD_TABLE(SYS_BASE_TABLE.SYS_BASE_MENU)+"  set actionid='' where actionid=?";
		 final String delete_menu_link_rel_sql = "DELETE FROM "+WSD_TABLE(SYS_BASE_TABLE.SYS_BASE_REL_MENU_LINK) +
			 		" where link_id=?"; 
		 try {
			 getDao().doInSingleTransationCircle("删除菜单", new SingleTransationCircleWithOutResult() {
				@Override
				public void actionInCircle() throws RuntimeException {
					try {
						getDao().deleteModuleById("删除链接", LinkResource.class,new Object[]{id});
						getDao().delete("删除菜单链接关系", delete_menu_link_rel_sql, new Object[]{id});
						getDao().update("清除菜单关联操作", update_actionid_sql, new Object[]{id});
					} catch (Exception e) {
						throw new RuntimeException(e);
					}
				}
			});
			 loadResourceToCache();
		} catch (DaoException e) {
			throw new ServiceException(e);
		}
	}
	/**
	 * 删除资源，同事删除下方的子菜单和操作，同时对同级菜单从当前菜单往后进行重新排序
	 * @param id
	 * @throws ServiceException
	 */
	public void deleteMenuResource(final String id) throws ServiceException {
		 final MenuResource resource = getMenuResourceById(id);
		 if(resource==null)throw new ServiceException("删除失败！");
		 Dao  dao = getDao();
		 //查找子菜单
		final List<String> cids = new ArrayList<String>();
		 cids.add(id);
		 try {
			dao.listRecursion("循环查找查找子菜单id", cids, 
					 "SELECT id,pid FROM "+WSD_TABLE(SYS_BASE_TABLE.SYS_BASE_MENU)+" where pid=?", "pid", "id", false, null, 
					 new Object[]{id}, 0);
		} catch (DaoException e1) {
			throw new ServiceException(e1);
		}
		 try {
			 getDao().doInSingleTransationCircle("删除菜单", new SingleTransationCircleWithOutResult() {
				@Override
				public void actionInCircle() throws RuntimeException {
					try {
						//根据关系表和菜单id查询链接id
						WhereCondition whereMenuCondition = new WhereCondition();
						whereMenuCondition.where().in("menu_id", cids);
						final String select_menu_link_rel_sql = "select link_id FROM "+WSD_TABLE(SYS_BASE_TABLE.SYS_BASE_REL_MENU_LINK);
						List<String> link_ids = getDao().listSignleStringColumn("获取链接ids", select_menu_link_rel_sql,whereMenuCondition, new Object[]{});
						 
						if(link_ids!=null&&!link_ids.isEmpty()){
							//删除菜单链接关系
							final String delete_menu_link_rel_sql = "DELETE FROM "+WSD_TABLE(SYS_BASE_TABLE.SYS_BASE_REL_MENU_LINK);
							getDao().delete("删除菜单链接关系", delete_menu_link_rel_sql, whereMenuCondition,new Object[]{});
							//删除链接
							final String delete_link_sql = "DELETE FROM "+WSD_TABLE(SYS_BASE_TABLE.SYS_BASE_LINK) ;
							WhereCondition whereLinkCondition = new WhereCondition();
							whereLinkCondition.where().in("id", link_ids);
							getDao().delete("删除链接", delete_link_sql,whereLinkCondition, new Object[]{});
						}
						//删除菜单
						WhereCondition whereCondition = new WhereCondition();
						whereCondition.where().in("id", cids);
						final String delete_menu_sql = "DELETE FROM "+WSD_TABLE(SYS_BASE_TABLE.SYS_BASE_MENU);
						getDao().delete("删除菜单", delete_menu_sql,whereCondition, new Object[]{});
						//同级菜单重新排序
						final  String update_order_sql = "UPDATE "+WSD_TABLE(SYS_BASE_TABLE.SYS_BASE_MENU)+" t set ordnum=ordnum-1 where ordnum>? and pid=?";
						getDao().update("同级菜单重新排序", update_order_sql, new Object[]{resource.getOrdNum(),resource.getPid()});
					} catch (Exception e) {
						throw new RuntimeException(e);
					}
				}
			});
			 loadResourceToCache();
		} catch (DaoException e) {
			throw new ServiceException(e);
		}
	}
	//
	/**
	 * 设置菜单为用户的默认菜单
	 * @param id
	 * @throws ServiceException
	 */
	public void setInitaction(final String id) throws ServiceException {
		MenuResource resource = getMenuResourceById(id);
		if(resource==null)throw new ServiceException("设置失败！");
		final  String update_action_sql_all_cancle = "UPDATE "+WSD_TABLE(SYS_BASE_TABLE.SYS_BASE_MENU)+"  set DEFAULTINIT=0 where DEFAULTINIT=1";
		final  String update_action_sql = "UPDATE "+WSD_TABLE(SYS_BASE_TABLE.SYS_BASE_MENU)+"  set DEFAULTINIT=1 where id=?";
		final Dao dao = getDao();
		 try {
				dao.doInSingleTransationCircle("新增菜单", new SingleTransationCircleWithOutResult() {
					@Override
					public void actionInCircle() throws RuntimeException {
						try {
							dao.update("设置菜单为用户的默认菜单", update_action_sql_all_cancle, new Object[]{});
							dao.update("设置菜单为用户的默认菜单", update_action_sql, new Object[]{id});
						} catch (DaoException e) {
							throw new RuntimeException(e);
						}
					}
				});
				loadResourceToCache();
			} catch (DaoException e) {
				throw new ServiceException(e);
			}
	}
	public MenuResource getDefaultInitResource() throws ServiceException{
		WhereCondition whereCondition  = new WhereCondition();
		whereCondition.where().eq("DEFAULTINIT","1");
		try {
			return 	CmCommon.getDao().getModule("获取资源路径id列表", MenuResource.class, whereCondition);
		} catch (DaoException e) {
			throw new ServiceException(e);
		}
	}
	/**
	 * 验证id是否存在
	 * @param id
	 * @return 存在返回true 不存在返回false
	 * @throws ServiceException 
	 */
	public boolean checkResId(String id) throws ServiceException {
		int num = 0;
		String sql = "SELECT count(id) FROM "+WSD_TABLE(SYS_BASE_TABLE.SYS_BASE_MENU)+" t WHERE t.id=?";
		try {
			num = getDao().queryForInt("验证资源id唯一性", sql, new Object[]{id});
		} catch (DaoException e) {
			throw new ServiceException(e);
		}
		return num!=0;
	}
	/**
	 * 将菜单资源加入缓存 ，删除，修改，添加资源都会进行此操作
	 * @throws ServiceException 
	 */
	public void loadResourceToCache() throws ServiceException {
		
		List<MenuResource> menusList = null;//所有菜单
		List<LinkResource> linkList = null;//所有操作
		
		Map<String, MenuResource> id_menuMap = new LinkedHashMap<String, MenuResource>();
		Map<String, LinkResource> id_linkMap = new LinkedHashMap<String, LinkResource>();
		Map<String, LinkResource> url_linkMap = new LinkedHashMap<String, LinkResource>();
		try {
			WhereCondition condition = new WhereCondition();
			condition.orderBy(" type, ordnum asc ");
			menusList = getDao().listModule("获取资源列表", MenuResource.class,condition);
			linkList = getDao().listModule("获取所有链接", LinkResource.class, null);
		} catch (DaoException e) {
			throw new ServiceException(e);
		}
		for (Iterator<LinkResource> iterator = linkList.iterator(); iterator.hasNext();) {
			LinkResource linkResource = (LinkResource) iterator.next();
			if (linkResource.getUrl() != null) {
				//setNavigate(linkResource);
				url_linkMap.put(linkResource.getUrl().toLowerCase(), linkResource);
				id_linkMap.put(linkResource.getId().toLowerCase(), linkResource);
			}
		}
		for (Iterator<MenuResource> iterator = menusList.iterator(); iterator.hasNext();) {
			MenuResource menuResource = iterator.next();
			//设置隐藏状态，如果上级是隐藏的这下级也隐藏
			setHiddenStatus(menuResource);
			setMenuChild(menuResource, menusList);
			if(isLinkGroup(menuResource)){
				setLinkChild(menuResource);
			}
			id_menuMap.put(menuResource.getId().toLowerCase(), menuResource);
			//判断顶层菜单是否有下级菜单，没有的话查出action
			//判断菜单是否是左侧最后一级别，如果是，需要查出他的连接地址
			setLinkSelected(menuResource, linkList);
			
		}
		List<String> publicURL = new ArrayList<String>();
		Map<String,LinkResource> publicResource = new HashMap<String,LinkResource>();
		//加载公共权限对应的连接
		WhereCondition whereCondition = new WhereCondition();
		whereCondition.andEq("r.ISPUBLIC", YESNO.YES.getStatus());
		List<LinkResource> publicResourceList =  getLinkResourceList(whereCondition);
		if(publicResourceList!=null){
			for (Iterator<LinkResource> iterator = publicResourceList.iterator(); iterator.hasNext();) {
				LinkResource u = iterator.next();
				String url = u.getUrl();
				if(StringUtils.hasText(url)){
					publicURL.add(url.toLowerCase());
				}
				publicResource.put(u.getId(), u);
			}
		}
		getCacheService().insertIntoCache(CacheGroupName.RESOURCE_CACHE,"将id_菜单资源加入缓冲", CACHEED_RESOURCE_ID_MENUS_COLLECTION_KEY, id_menuMap);
		getCacheService().insertIntoCache(CacheGroupName.RESOURCE_CACHE,"将id_菜单资源加入缓冲", CACHEED_RESOURCE_ID_LINKS_COLLECTION_KEY, id_linkMap);
		getCacheService().insertIntoCache(CacheGroupName.RESOURCE_CACHE,"将id_菜单资源加入缓冲", CACHEED_RESOURCE_URL_COLLECTION_KEY, url_linkMap);
		getCacheService().insertIntoCache(CacheGroupName.RESOURCE_CACHE,"将id_菜单资源加入缓冲", CACHEED_PUBLIC_URL_COLLECTION_KEY, publicURL);
		getCacheService().insertIntoCache(CacheGroupName.RESOURCE_CACHE,"将id_菜单资源加入缓冲", CACHEED_PUBLIC_RESOURCE_COLLECTION_KEY, publicResource);
	}
	private void setHiddenStatus(MenuResource urlResource) throws ServiceException {
		try {
			List<String> ids = new ArrayList<String>();
			CmCommon.getDao().listRecursion("获取父级菜单IDS", ids, 
					"SELECT id,pid FROM "+WSD_TABLE(Table.SYS_BASE_TABLE.SYS_BASE_MENU)+" where id=?", 
					"pid", "id", true, null, new Object[]{urlResource.getId()}, 0);
			if(CollectionUtil.hasElement(ids)){
				String sql = "select count(*) from "+WSD_TABLE(Table.SYS_BASE_TABLE.SYS_BASE_MENU)+"  where hidden='1'";
				WhereCondition condition = new WhereCondition();
				condition.and().in("id", ids);
				int num =  CmCommon.getDao().queryForInt("获取父级菜单是否隐藏", sql, condition,new Object[]{});
				if(num>0){
					urlResource.setHidden(YESNO.YES.getStatus());
				}
			}
		} catch (DaoException e) {
			throw new ServiceException(e);
		}
	}
	public static boolean inPublic(String url){
		@SuppressWarnings("unchecked")
		List<String>  publicURL = (List<String>) getCacheService().getFromCacheByKey(CacheGroupName.RESOURCE_CACHE, "获取公共资源", CACHEED_PUBLIC_URL_COLLECTION_KEY);
		if(StringUtils.hasText(url)&&publicURL!=null&&publicURL.contains(url.toLowerCase()))return true;
		return false;
	}
	/**
	 * 获取公共角色对应的资源
	 * @return
	 * @throws ServiceException
	 */
	public List<LinkResource> getLinkResourceList(WhereCondition whereCondition) throws ServiceException{
		String public_sql = "SELECT l.* FROM " + WSD_TABLE(SYS_BASE_TABLE.SYS_BASE_LINK) + " l ," + 
				 		 WSD_TABLE(SYS_BASE_TABLE.SYS_BASE_REL_MENU_LINK)+" ml," +
	                     WSD_TABLE(SYS_BASE_TABLE.SYS_BASE_REL_RIGHT_MENU)+" rm," +
	                     WSD_TABLE(SYS_BASE_TABLE.SYS_BASE_RIGHT) + " r "
				+ " WHERE  r.id=rm.right_id and rm.menu_id=ml.menu_id and ml.link_id=l.id ";
		try {
			return  CmCommon.getDao().listModule("获取公共资源列表", public_sql, LinkResource.class,whereCondition);
		} catch (DaoException e) {
			throw new ServiceException(e);
		}
	}
	/**
	 * 给操作添加导航属性
	 * @param urlResource
	 * @throws ServiceException
	 *//*
	private void setNavigate(LinkResource urlResource) throws ServiceException {
			String get_shortNamepath_sql = 
					" SELECT shortname FROM "+WSD_TABLE(Table.SYS_BASE_TABLE.SYS_BASE_MENU) +
					" s START WITH s.id=(select s.id  from "+WSD_TABLE(Table.SYS_BASE_TABLE.SYS_BASE_MENU)+"  m,"+
					  WSD_TABLE(Table.SYS_BASE_TABLE.SYS_BASE_REL_MENU_LINK)+ " ml where m.id=ml.menu_id and ml.link_id=?)  " +
					" CONNECT BY prior  s.pid=s.id " +
					" ORDER BY level desc";
			try {
				String navigate = "";
				List<String> shortNamePath =  CmCommon.getDao().listSignleStringColumn("获取资源路径id列表", get_shortNamepath_sql, null, new Object[]{urlResource.getId()});
				if(shortNamePath!=null){
					for (Iterator<String> iterator = shortNamePath.iterator(); iterator
							.hasNext();) {
						String parent = iterator.next();
						navigate += parent;
						if(iterator.hasNext())navigate += " >> ";
					}
				}
				urlResource.setNavigate(navigate);
			} catch (DaoException e) {
				throw new ServiceException(e);
			}
	}*/
	public static MenuResource getMenuResourceFromCache(String rsId){
		Map<String, MenuResource> resourceMap = getAllMenuResourceFromCache();
		if(resourceMap!=null)return resourceMap.get(rsId.toLowerCase());
		return null;
	}
	public static LinkResource getLinkResourceFromCache(String rsId){
		Map<String, LinkResource> resourceMap = getAllLinkResourceFromCache();
		if(resourceMap!=null)return resourceMap.get(rsId.toLowerCase());
		return null;
	}
	/**
	 * 获取所有菜单
	 * @param userId 
	 * @return
	 * @throws ServiceException
	 */
	@SuppressWarnings("unchecked")
	public static Map<String,MenuResource> getAllMenuResourceFromCache()  {
		return (Map<String,MenuResource>)  getCacheService().getFromCacheByKey(CacheGroupName.RESOURCE_CACHE,"获取全部缓冲的菜单资源", CACHEED_RESOURCE_ID_MENUS_COLLECTION_KEY);
	}
	/**
	 * 获取所有链接
	 * @param userId 
	 * @return
	 * @throws ServiceException
	 */
	@SuppressWarnings("unchecked")
	public static Map<String,LinkResource> getAllLinkResourceFromCache()  {
		return (Map<String,LinkResource>)  getCacheService().getFromCacheByKey(CacheGroupName.RESOURCE_CACHE,"获取全部缓冲的菜单资源", CACHEED_RESOURCE_ID_LINKS_COLLECTION_KEY);
	}
	@SuppressWarnings("unchecked")
	public static String getNavigate(String url){
		Map<String, MenuResource> urlResourceMap = (Map<String, MenuResource>)  getCacheService().getFromCacheByKey(CacheGroupName.RESOURCE_CACHE,"获取菜单资源url对应的资源", CACHEED_RESOURCE_URL_COLLECTION_KEY);
		MenuResource resource = null;
		if(urlResourceMap!=null&&!urlResourceMap.isEmpty()&&((resource=urlResourceMap.get(url.toLowerCase()))!=null)){
			return resource.getNavigate();
		}
		return null;
	}
	/**
	 * 是否是叶子菜单（没有子菜单）
	 * @param pid
	 * @return
	 * @throws ServiceException
	 */
	public  static boolean isLastMenu(MenuResource resource) throws ServiceException {
		boolean isLastLeftResource = false;
		String sql = "SELECT count(id) FROM "+WSD_TABLE(SYS_BASE_TABLE.SYS_BASE_MENU)+" t where t.pid=? ";
		try {
			int num =  CmCommon.getDao().get("获取子菜单排序的最大值", sql, new SingleColumnRowMapper<Integer>(Integer.class), new Object[]{resource.getId()});
			isLastLeftResource = (num==0);
		} catch (DaoException e) {
			throw new ServiceException(e);
		}
		return isLastLeftResource;
	}
	/***
	 * 将子菜单查出付给父菜单
	 * @param urlResource
	 * @param resList
	 */
	private static void setMenuChild(MenuResource menuResource, List<MenuResource> resList) {
		if(!menuResource.isLeafMenu()){
			for (Iterator<MenuResource> iterator = resList.iterator(); iterator.hasNext();) {
				MenuResource rs = (MenuResource) iterator.next();
				if(rs.getPid().equalsIgnoreCase(menuResource.getId())){
					if(isLinkGroup(rs)){//如果下级是链接组，说明是最底层菜单
						menuResource.setLeafMenu(true);
					}
					menuResource.getChildMenuResource().add(rs);
				}
			}
		}
	}
	/***
	 * 将子链接查出付给父菜单
	 * @param urlResource
	 * @param resList
	 * @throws ServiceException 
	 */
	private static void setLinkChild(MenuResource menuResource) throws ServiceException {
		menuResource.getChildLinkResource().addAll(getLinkResourcesByMenuId(menuResource.getId()));
	}
	/***
	 * 将设置的链接查出付给菜单
	 * @param urlResource
	 * @param resList
	 * @throws ServiceException 
	 */
	private static void setLinkSelected(MenuResource menuResource,List<LinkResource> linkList) throws ServiceException {
		if(menuResource.isLeafMenu()&&StrUtil.isNotBank(menuResource.getActionId())){
			int index = -1;
			if((index=linkList.indexOf(new LinkResource(menuResource.getActionId())))!=-1){
				LinkResource linkResource = linkList.get(index);
				setMenuHasAction(menuResource,linkResource);
			}
		}
	}
	/**
	 * 修改菜单之后重新加载tree
	 * @return
	 * @throws ServiceException
	 */
	public String reloadTree() throws ServiceException {
		return getResource(null);
	}
	/**
	 * 根据菜单类型获取菜单
	 * @param userId 
	 * @param userId 
	 * @return
	 * @throws ServiceException
	 */
	public Map<String,MenuResource> getResourceFromCache(Collection<MenuResource>  resources,ResourceFilter resourceFilter)  {
		Map<String,MenuResource> returnMap = new LinkedHashMap<String, MenuResource>();
		
		for (Iterator<MenuResource> iterator = resources.iterator(); iterator.hasNext();) {
			MenuResource resource = iterator.next();
			if(resourceFilter.selectCurrentNode(resource)){
				returnMap.put(resource.getId(), resource);
			}
		}
		return returnMap;
	}
	/**
	 * 根据菜单类型获取菜单
	 * @param userId 
	 * @return
	 * @throws ServiceException
	 *//*
	@SuppressWarnings("unchecked")
	public Map<String,UrlResource> getUserMenuResourceFromCache(Map<String,UrlResource> menuResource,String userId)  {
		Map<String,UrlResource> returnMap = new LinkedHashMap<String, UrlResource>();
		
		if(!StringUtils.hasText(userId))return menuResource;
		Map<String, List<String>> resid_userIds = (Map<String, List<String>>) getCache().
		getAuthData("获取连接对应的用户列表资源", CACHEED_RESOURCEID_USERIDS_COLLECTION_KEY);
		for (Iterator<String> iterator = menuResource.keySet().iterator(); iterator.hasNext();) {
			String id =  iterator.next();
			UrlResource resource =  menuResource.get(id);
			if(resid_userIds.get(id).contains(userId)){
				returnMap.put(id, resource);
			}
		}
		return returnMap;
	}
	
	*//**
	 * 根据菜单类型获取菜单
	 * @param userId 
	 * @return
	 * @throws ServiceException
	 *//*
	@SuppressWarnings("unchecked")
	public Map<String,UrlResource> getUrlResourceFromCache(Map<String,UrlResource> menuResource,String userId)  {
		Map<String,UrlResource> returnMap = new LinkedHashMap<String, UrlResource>();
		
		if(!StringUtils.hasText(userId))return menuResource;
		Map<String, List<String>> url_userIds = (Map<String, List<String>>) getCache().
				getAuthData("获取连接对应的用户列表资源", CACHEED_URL_USERIDS_COLLECTION_KEY);
		for (Iterator<String> iterator = menuResource.keySet().iterator(); iterator.hasNext();) {
			String id =  iterator.next();
			UrlResource resource =  menuResource.get(id);
			if(url_userIds.values().contains(userId)){
				returnMap.put(id, resource);
			}
		}
		return returnMap;
	}*/
	
	/**
	 * var zNodes =[
	 			{ id:1, pId:0, name:"随意勾选 1", open:true},
	 			{ id:11, pId:1, name:"随意勾选 1-1"},
	 			{ id:12, pId:1, name:"随意勾选 1-2", open:true},
	 			{ id:121, pId:12, name:"随意勾选 1-2-1"},
	 			{ id:122, pId:12, name:"随意勾选 1-2-2"},
	 			{ id:2, pId:0, name:"禁止勾选 2", open:true, doCheck:false},
	 			{ id:21, pId:2, name:"禁止勾选 2-1", doCheck:false},
	 			{ id:22, pId:2, name:"禁止勾选 2-2", checked:true, open:true, doCheck:false},
	 			{ id:221, pId:22, name:"禁止勾选 2-2-1", doCheck:false},
	 			{ id:222, pId:22, name:"禁止勾选 2-2-2", checked:true, doCheck:false},
	 			{ id:23, pId:2, name:"禁止勾选 2-3", doCheck:false}
	 		];
	 * 构造ztree所需的数据 统一的方法，根据传入的filter来控制菜单的显示，打开等属性
	 * @param parameter,String[] roleIds 角色id，如果不为空，将根据该角色进行初始化选择，如果没有选择，就不显示
	 * @return
	 * @throws ServiceException 
	 */
	public String getResource(ResourceFilter filter ) throws ServiceException{
		StringBuilder resourceTreeData = new StringBuilder();
		resourceTreeData.append("[");
		resourceTreeData.append("{icon:'\'+_rs_image_path+\'/rsroot.png',id:0, pId:-1, name:'资源树', open:true,nocheck:true,rstype:'-1'}");
		Map<String,MenuResource> allMenuResource = getAllMenuResourceFromCache();
		for (Iterator<MenuResource> iterator = allMenuResource.values().iterator(); iterator.hasNext();) {
			MenuResource resource =  iterator.next();
			
			boolean checked = false;
			boolean isOpen = false;
			boolean nocheck = false;
			if(filter!=null){
				if(filter.selectCurrentNode(resource))checked=true;
				if(filter.removeCurrentNode(resource))continue;
				if(filter.openCurrentNode(resource))isOpen=true;
				if(filter.nocheck(resource))nocheck=true;
			}
			resourceTreeData.append(",{");
			
			String shortName = resource.getShortName();
			if(YESNO.YES.getStatus().equals(resource.getHidden())){
				//resourceTreeData.append("font:{'text-decoration': 'line-through'},");
				shortName+="(已隐藏)";
			}
			if(!CoreInitCtx.isProductMode()&&YESNO.YES.getStatus().equals(resource.getFordev())){//开发模式下的菜单
				 shortName+="(仅开发模式)";
		     }
			if(isTopMenu(resource)){
				resourceTreeData.append("icon:'\'+_rs_image_path+\'/rstop.gif',");
			}
			if(isLeftMenu(resource)){
				resourceTreeData.append("icon:'\'+_rs_image_path+\'/rsleft.gif',");
			}
			if(isLinkGroup(resource)){
				resourceTreeData.append("icon:'\'+_rs_image_path+\'/lg.png',");
			}
			resourceTreeData.append("id:'").append(resource.getId()).append("',");
			resourceTreeData.append("pId:'").append(resource.getPid()).append("',");
			resourceTreeData.append("name:'").append(shortName).append("',");
			resourceTreeData.append("actionid:'").append(resource.getActionId()).append("',");
			resourceTreeData.append("checked:").append(checked).append(",");
			resourceTreeData.append("open:").append(isOpen).append(",");
			resourceTreeData.append("nocheck:").append(nocheck).append(",");
			resourceTreeData.append("rstype:'").append(resource.getType()).append("'");
			resourceTreeData.append("}");
			//链接
			if(isLastMenu(resource)){
				List<LinkResource> childLinkResources = resource.getChildLinkResource();
				if(CollectionUtil.hasElement(childLinkResources)){
					for (Iterator<LinkResource> iterator2 = childLinkResources.iterator(); iterator2
							.hasNext();) {
						
						LinkResource linkResource = (LinkResource) iterator2
								.next();
						String l_shortName =  linkResource.getShortName();
						boolean l_checked = false;
						boolean l_isOpen = false;
						boolean l_nocheck = false;
						if(filter!=null){
							if(filter.selectCurrentNode(linkResource))l_checked=true;
							if(filter.removeCurrentNode(linkResource))continue;
							if(filter.nocheck(linkResource))l_nocheck=true;
						}
						resourceTreeData.append(",{");
						if(!CoreInitCtx.isProductMode()&&YESNO.YES.getStatus().equals(linkResource.getFordev())){//开发模式下的链接
							l_shortName+="(仅开发模式)";
					     }
						resourceTreeData.append("icon:'\'+_rs_image_path+\'/rslink.gif',");
						resourceTreeData.append("id:'").append(linkResource.getId()).append("',");
						resourceTreeData.append("pId:'").append(resource.getId()).append("',");
						resourceTreeData.append("name:'").append(l_shortName).append("',");
						resourceTreeData.append("checked:").append(l_checked).append(",");
						resourceTreeData.append("open:").append(l_isOpen).append(",");
						resourceTreeData.append("nocheck:").append(l_nocheck).append(",");
						resourceTreeData.append("rstype:'").append(MenuResource.ResourceType.ACTION.getCode()).append("'");
						resourceTreeData.append("}");
					}
				}
				
			}
		}
		resourceTreeData.append("]");
		logger.debug("资源树数据："+resourceTreeData.toString());
		return resourceTreeData.toString();
	}
	/**
	 * 是否顶部菜单
	 * @param resource
	 * @return
	 */
	public static boolean isTopMenu(MenuResource resource ){
		return resource!=null&&resource.getPid().equalsIgnoreCase(RES_ROOT_ID);
	}
	/**
	 * 是否左侧菜单
	 * @param resource
	 * @return
	 */
	public static boolean isLeftMenu(MenuResource resource ){
		return resource!=null&&MenuResource.ResourceType.MENU.getCode().equals(resource.getType())&&!resource.getPid().equalsIgnoreCase(RES_ROOT_ID);
	}
	/**
	 * 是否链接分组
	 * @param resource
	 * @return
	 */
	public static  boolean isLinkGroup(MenuResource resource ){
		return resource!=null&&MenuResource.ResourceType.ACTION_GROUP.getCode().equals(resource.getType())&&!resource.getPid().equalsIgnoreCase(RES_ROOT_ID);
	}
	/**
	 * 修改菜单的顺序，例如：上移，下移
	 * @param selectedNodeId
	 * @param type
	 * @throws NiceException
	 * @throws ServiceException
	 */
	public void changeResourceOrder(final String selectedNodeId, String type) throws NiceException, ServiceException {
		final MenuResource selectedUrlResource;
		try {
			selectedUrlResource = getMenuResourceById(selectedNodeId);
		} catch (ServiceException e) {
			throw new ServiceException(e);
		}
		if(selectedUrlResource==null)throw new NiceException("id 为"+selectedNodeId+" 的菜单已经不存在！");
		final int newOrder = "up".equalsIgnoreCase(type)?(selectedUrlResource.getOrdNum()-1):(selectedUrlResource.getOrdNum()+1);
		final String sql_1 = "UPDATE "+WSD_TABLE(SYS_BASE_TABLE.SYS_BASE_MENU)+" SET ordnum=? WHERE id=?";
		final String sql_2 = "UPDATE "+WSD_TABLE(SYS_BASE_TABLE.SYS_BASE_MENU)+" SET ordnum=? WHERE pid=? and ordNum=?";
		final Dao dao = getDao();
		try {
			dao.doInSingleTransationCircle("菜单排序", new SingleTransationCircleWithOutResult() {
				@Override
				public void actionInCircle() throws RuntimeException {
					try {
						dao.update("新增移动", sql_2,new Object[]{selectedUrlResource.getOrdNum(),selectedUrlResource.getPid(),newOrder});
						dao.update("菜单移动", sql_1, new Object[]{newOrder,selectedNodeId});
					} catch (DaoException e) {
						throw new RuntimeException(e);
					}
				}
			});
			loadResourceToCache();
		} catch (DaoException e) {
			throw new ServiceException(e);
		}
	}
	/**
	 * 获取用来进行初始界面设置的树形结构
	 * @param selectedNodeId
	 * @return
	 * @throws ServiceException
	 */
	public String getMenusResource(final String selectedNodeId) throws ServiceException {
		final MenuResource resource = getMenuResourceById(selectedNodeId);
		final String actionid = resource.getActionId()==null?"":resource.getActionId();
		final List<String> initIdPath = getMenuInitResIdPath(actionid);
		 ResourceFilter filter = new ResourceFilter() {
			@Override
			public boolean selectCurrentNode(MenuResource resource) {
				return initIdPath.contains(resource.getId());
			}
			@Override
			public boolean removeCurrentNode(MenuResource resource) {
				return false;
			}
			@Override
			public boolean openCurrentNode(MenuResource resource) {
				return initIdPath.contains(resource.getId())||resource.getId().equalsIgnoreCase(selectedNodeId);
			}
			@Override
			public boolean nocheck(MenuResource resource) {
				return true;
			}
			@Override
			public boolean selectCurrentNode(LinkResource linkResource) {
				return actionid.equalsIgnoreCase(linkResource.getId());
			}
			@Override
			public boolean removeCurrentNode(LinkResource linkResource) {
				return false;
			}
			@Override
			public boolean nocheck(LinkResource linkResource) {
				 return false;
			}
		};
		return getResource(filter);
	}
	/**
	 * 获取从当前菜单开始往下的菜单id路径
	 * @param initId
	 * @return
	 * @throws ServiceException
	 */
	public List<String> getMenuInitResIdPath(String initId) throws ServiceException{
		WhereCondition searchParameter = new WhereCondition();
		searchParameter.eq("ID", initId);
		List<String> initResIdPath = new ArrayList<String>();
		initResIdPath.addAll(getResourcePath(initId));
		return initResIdPath;
	}
	/**
	 * 获取从当前菜单开始往上的菜单id路径
	 * @param menuNode2Id
	 * @return
	 * @throws ServiceException
	 */
	public List<String> getResourcePath(String menuNode2Id) throws ServiceException {
		List<String> ids = new ArrayList<String>();
		ids.add(menuNode2Id);
		try {
			CmCommon.getDao().listRecursion("获取父级菜单IDS", ids, 
					"SELECT id,pid FROM "+WSD_TABLE(Table.SYS_BASE_TABLE.SYS_BASE_MENU)+" where id=?", 
					"pid", "id", true, null, new Object[]{menuNode2Id}, 0);
			return 	ids;
		} catch (DaoException e) {
			throw new ServiceException(e);
		}
	}
	/**
	 * 菜单设置操作
	 * @param res
	 * @throws ServiceException
	 */
	public void setMenuAction(MenuResource menuResource,String linkId )  throws ServiceException{
		MenuResource menuResourceDb = getMenuResourceById(menuResource.getId());
		menuResourceDb.setActionId(linkId);
		menuResourceDb.setOpenNewWindow(menuResource.getOpenNewWindow());
		menuResourceDb.setOpen(menuResource.getOpen());
		menuResourceDb.setModified(new Date());
		menuResourceDb.setMuid(BaseController.getUid());
		try {
			CmCommon.getDao().updateModuleById("设置菜单操作", menuResourceDb, new String[]{});
			loadResourceToCache();
		} catch (DaoException e) {
			throw new ServiceException(e);
		}
	}
	/**
	 * 菜单设置操作
	 * @param res
	 * @throws ServiceException
	 */
	public static void setMenuHasAction(MenuResource menuResource,LinkResource linkResource)  throws ServiceException{
		if(linkResource!=null){
			menuResource.setUrl(linkResource.getUrl());
			//设置外链前缀来自配置文件的情况
			if(linkResource.getOuturl().equalsIgnoreCase(YESNO.YES.getStatus())){
				if(LinkOwnerType.OUT_SYS_WITH_PREFIX_CONFIGED.getCode().equalsIgnoreCase(linkResource.getOwnerType())){
					String preficConf = linkResource.getOwnerUrlPreFix();
					if(StrUtil.isNotBank(preficConf)){
						String[] cs = preficConf.split("@");
						if(cs.length!=2){
							logger.error("资源"+linkResource+"解析失败,前缀"+preficConf+"错误");
						}else{
							String key = cs[0];
							String properties = cs[1];
							String prefix = ParaGetTool.getParaFromProperties(properties, key);
							menuResource.setUrl(prefix+linkResource.getUrl());
						}
					}
				}
			}
			menuResource.setOuturl(linkResource.getOuturl());
			menuResource.setExtFlag(linkResource.getShortName()+"("+menuResource.getUrl()+")");
			menuResource.setLeafMenu(true);
		}
	}
	/**
	 * 添加链接时选择链接分组
	 * @param selectedNodeId
	 * @return
	 * @throws ServiceException 
	 */
	public List<MenuResource> getLinkGroupForLinkShare(String selectedId,OPERATION_TYPE type) throws ServiceException {
		String sql = null;
		Object[] args =  new Object[]{};
		if(OPERATION_TYPE.ADD==type){
			sql = "select m.* from "+WSD_TABLE(Table.SYS_BASE_TABLE.SYS_BASE_MENU)+
				" m where m.pid=(select pid from "+WSD_TABLE(Table.SYS_BASE_TABLE.SYS_BASE_MENU)+"  s where s.id=?)";
			args = new Object[]{selectedId};
		}else if(OPERATION_TYPE.UPDATE==type){
			sql = "select a.*,b.checked from(select m.* from "+
		            WSD_TABLE(Table.SYS_BASE_TABLE.SYS_BASE_MENU)+
					" m where m.pid=(select distinct pid from "+WSD_TABLE(Table.SYS_BASE_TABLE.SYS_BASE_MENU)+"  s," +
					WSD_TABLE(Table.SYS_BASE_TABLE.SYS_BASE_REL_MENU_LINK)+
					" ml where ml.menu_id=s.id and ml.link_id=? )) a "+
					" left join " +
					"(select m.*, '1' checked from "+WSD_TABLE(Table.SYS_BASE_TABLE.SYS_BASE_MENU)+" m,"+
					WSD_TABLE(Table.SYS_BASE_TABLE.SYS_BASE_REL_MENU_LINK)+
					" ml where ml.menu_id=m.id and ml.link_id=?)b on a.id=b.id";
			args = new Object[]{selectedId,selectedId};
		}else if(OPERATION_TYPE.GET==type){
			sql = "select m.*, '1' checked from "+WSD_TABLE(Table.SYS_BASE_TABLE.SYS_BASE_MENU)+" m,"+
					WSD_TABLE(Table.SYS_BASE_TABLE.SYS_BASE_REL_MENU_LINK)+
					" ml where ml.menu_id=m.id and ml.link_id=?";
			args = new Object[]{selectedId};
		}
		try {
			return getDao().listModule("获取链接分组", sql, MenuResource.class, args);
		} catch (DaoException e) {
			throw new ServiceException(e);
		}
	}
}

